package org.lanqiao.util;


import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class DBUtil {
    //获取数据源
    public static DataSource getDruidDataSource() {
        DataSource dataSource = null;
        Properties pro = new Properties();
        InputStream stream = DBUtil.class.getClassLoader().getResourceAsStream("druid.properties");
        try {
            //加载 druid.properties  配置信息
            pro.load(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //创建 dataSource
        try {
            dataSource = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataSource;
    }

    //数据库连接
    public static Connection getConn() {
        DataSource dataSource = DBUtil.getDruidDataSource();
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;

    }

    // 测试链接数据库是否出成功
    public static void main(String[] args) {
        System.out.println(DBUtil.getConn());
    }

    //释放资源的方法
    public static void closeAll(ResultSet resultSet, PreparedStatement pst, Connection conn) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (pst != null) {
                pst.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //增删改方法
    public static int executeUpdate(String sql, Object... objects) {
        // 1. 获取连接
        Connection conn = DBUtil.getConn();
        PreparedStatement pst = null;
        int row = -1;
        try {
            // 2. 创建一个PreparedStatement对象（sql语句）
            pst = conn.prepareStatement(sql);
            // 3. 给参数赋值
            for (int i = 0; i < objects.length; i++) {
                pst.setObject(i + 1, objects[i]);
            }
            //4. 执行sql，(获取返回结果)返回影响的行数
            row = pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeAll(null, pst, conn);
        }
        return row;
    }

    //查询的方法
    public static <T> List<T> executeQuery(Class<T> clazz, String sql, Object... objects) {
        List<T> list = new ArrayList<>();
        //1. 获取链接
        Connection conn = DBUtil.getConn();
        PreparedStatement pst = null;
        ResultSet resultSet = null;
        try {
            //2. 获取pst
            pst = conn.prepareStatement(sql);
            // 3. 给参数赋值
            for (int i = 0; i < objects.length; i++) {
                pst.setObject(i + 1, objects[i]);
            }
            //4. 执行sql，获取返回结果集 执行查询，处理返回结果
            resultSet = pst.executeQuery();
            //获取元数据
            ResultSetMetaData rmd = resultSet.getMetaData();
            //获取列的数量
            int count = rmd.getColumnCount();

            while (resultSet.next()) {
                try {
                    T t = clazz.newInstance();
                    for (int i = 0; i < count; i++) {
                        String label = rmd.getColumnLabel(i + 1);
                        Object obj = resultSet.getObject(label);
                        //获取属性并给属性赋值
                        Field field = clazz.getDeclaredField(label);


                        field.setAccessible(true);
                        field.set(t, obj);
                    }
                    list.add(t);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeAll(resultSet, pst, conn);
        }
        return list;
    }


}
